#######################################
# 提供一些工具函数
#######################################
import numpy as np
from os import path

# Q8.8量化 即8位整数 8位小数
# a的范围应在[-128.99609375, 127.99609375]
def np_quant(a):
    if np.max(a) > 127.99609375 or np.min(a) < -128.99609375:
        print('out of range')
        return None
    return np.round(a * 256).astype(np.int16)
# 反量化
def np_dequant(a):
    return a.astype(np.float) / 256.

fmt='''
#ifndef {0}
#define {0}

#include "dtype.h" // you should specify data type in this file

const INT16 {1}{2}={{
{3}
}};

#endif

'''

def get_dim_str(a):
    return '[' + ']['.join(list(map(str, a.shape))) + ']'

# a: np.array
# col: Columns
def np2str(a, col=8):
    ret = ''
    cnt = 0
    for var in a.flatten():
        ret += '{0}, '.format(str(var))
        cnt += 1
        if cnt % col == col -1:
            ret += '\n'
    return ret

# 本函数用于将numpy数组保存为C语言头文件
def np2c_header(a, fname='data'):
    with open(fname + '.h', 'w') as fp:
        fp.write(
            fmt.format(
                '_' + path.split(fname)[-1].replace('.', '_').upper() + '__H_',
                path.split(fname)[-1].replace('.', '_'),
                get_dim_str(a),
                np2str(a)
            )
        )

def test():
    # a = np.random.randn(1,6,28,28)
    a = (np.random.randn(1,6,28,28)*2**12).astype(np.int32)
    print(get_dim_str(a))
    print(np2str(a,4))
    np2c_header(a)
    pass

if __name__ == "__main__":
    test()